﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Common;

namespace TransferServer
{
    public partial class TransferMainForm : Form
    {
        private Socket _tcpListener;
        private Thread _tTcpLinsten;

        private readonly Hashtable _acceptServertIpList = Hashtable.Synchronized(new Hashtable());
        private readonly Hashtable _acceptServersocketList = Hashtable.Synchronized(new Hashtable());

        private readonly ArrayList _alThread = new ArrayList();

        private const string StrVersion = "当前版本号：1.0.0";
        public TransferMainForm()
        {
            InitializeComponent();
            label_version1.Text = StrVersion;
        }




        private void TransferMainForm_Load(object sender, EventArgs e)
        {
            label_ListenPort.Text = "监听端口：" + ConstParameters.TransferListenPort;
            button_Stop.Enabled = false;

            InitControlAfterStartService();
            _tTcpLinsten = new Thread(TcpLinsten) { IsBackground = true };
            _tTcpLinsten.Start();
        }

        private void button_Start_Click(object sender, EventArgs e)
        {
            InitControlAfterStartService();
            _tTcpLinsten = new Thread(TcpLinsten) { IsBackground = true };
            _tTcpLinsten.Start();
        }

        private void button_Stop_Click(object sender, EventArgs e)
        {
            _tcpListener.Close();
            _tTcpLinsten.Abort();

            foreach (Thread thread in _alThread)
            {
                if (thread == null)
                    return;
                try
                {
                    thread.Abort();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            _acceptServertIpList.Clear();
            _acceptServersocketList.Clear();
            InitControlAfterStopService();
        }



        //!--3
        private void TcpLinsten()
        {
            IPEndPoint myServer = new IPEndPoint(IPAddress.Any, ConstParameters.TransferListenPort);
            try
            {
                _tcpListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _tcpListener.Bind(myServer);
                _tcpListener.Listen(0);
                _alThread.Clear();
                while (true)
                {
                    Socket ss = _tcpListener.Accept();
                    ss.NoDelay = true;
                    Thread t = new Thread(RecieveData) { IsBackground = true, Name = ((IPEndPoint)(ss.RemoteEndPoint)).Address.ToString() };
                    t.Start(ss);
                    _alThread.Add(t);
                }
            }
            catch (Exception ex)
            {
                CommonRoutine.HandlingExceptions(ex);
                if (_tcpListener != null)
                {
                    _tcpListener.Close();
                }
                BeginInvoke(new MethodInvoker(InitControlAfterStopService));
            }
        }


        private void RecieveData(object obj)
        {
            Socket tcpClient = obj as Socket;
            if (tcpClient == null) return;
            string clientIp = ((IPEndPoint)(tcpClient.RemoteEndPoint)).Address.ToString();
            string flag = clientIp;
            List<byte> receBufferBb = new List<byte>();
            #region
            while (true)
            {
                byte[] receBuffer = new byte[100];
                #region rece Data
                try
                {
                    int receDataLength = tcpClient.Receive(receBuffer);
                    Thread.Sleep(1);
                    if (receDataLength == 0 || receDataLength == -1)
                    {
                        break;
                    }
                    byte[] temp = new byte[receDataLength];
                    Array.Copy(receBuffer, 0, temp, 0, temp.Length);
                    receBufferBb.AddRange(temp);
                }
                catch (Exception ex)
                {
                    CommonRoutine.HandlingExceptions(ex);
                    tcpClient.Close();
                    break;
                }


                #endregion


                int receBufferBBindex = 0;
                int sendflag = -1;
                int endindex = 0;
                List<byte> receByteList = new List<byte>();

                foreach (byte b in receBufferBb)
                {
                    receBufferBBindex++;
                    if (b == 0x7e) sendflag++;
                    if (sendflag >= 0)
                    {
                        if (sendflag == 0) { receByteList.Add(b); }
                        else if (sendflag == 1)
                        {
                            receByteList.Add(b);
                            byte[] receData = receByteList.ToArray();
                            receByteList.Clear();
                            sendflag = -1;
                            endindex = receBufferBBindex;

                            #region
                            byte[] realData = OperateAgreement.RestoreReceData(receData);
                            if (OperateAgreement.JudgeisCompleteData(realData))
                            {
                                // IP---------ArrayList-------phonenuber
                                string phoneNumber = OperateAgreement.GetPhoneNumInMessageHead(realData);
                                ushort messageId = OperateAgreement.GetMessageIdInMessageHead(realData);

                                if (messageId == ConstParameters.CmdRetweet ||
                                    messageId == ConstParameters.CmdRetweetTaxiDispatchClient ||
                                   messageId == ConstParameters.CmdRetweetTaxiDispatchClientNoipInData)
                                {
                                    string ss = OperateAgreement.GetPhoneNumInTransferMessageHead(realData);
                                    LogService.WriteDebugLog("接受到需要转发的消息,需要发送到：" + ss + "  ,  messageId:" + messageId.ToString("X2").PadLeft(4, '0'), DateTime.Now, "Retweet");
                                    if (messageId == ConstParameters.CmdRetweetTaxiDispatchClient
                                        || messageId == ConstParameters.CmdRetweetTaxiDispatchClientNoipInData)
                                    {
                                        byte[] IpBytes = ((IPEndPoint)(tcpClient.RemoteEndPoint)).Address.GetAddressBytes();
                                        flag = clientIp + "c";
                                        if (messageId == ConstParameters.CmdRetweetTaxiDispatchClient)
                                        {
                                            realData[25] = IpBytes[0];
                                            realData[26] = IpBytes[1];
                                            realData[27] = IpBytes[2];
                                            realData[28] = IpBytes[3];
                                            realData[realData.Length - 2] = CommonRoutine.GetCheckBit(realData);
                                            receData = OperateAgreement.TransferToSendData(realData);
                                        }
                                        _acceptServersocketList[flag] = tcpClient;

                                    }
                                    else
                                    {
                                        #region Register
                                        if (!_acceptServersocketList.Contains(flag))
                                        {
                                            _acceptServersocketList[flag] = tcpClient;
                                        }
                                        ArrayList altemp = _acceptServertIpList[flag] as ArrayList;
                                        if (altemp == null)
                                        {
                                            altemp = new ArrayList { phoneNumber };
                                        }
                                        else if (!altemp.Contains(phoneNumber))
                                        {
                                            altemp.Add(phoneNumber);
                                        }

                                        _acceptServertIpList[flag] = altemp;
                                        #endregion
                                    }


                                    string realPhoneNumber = OperateAgreement.GetPhoneNumInTransferMessageHead(realData);
                                    lock (_acceptServertIpList.SyncRoot)
                                    {
                                        foreach (DictionaryEntry d in _acceptServertIpList)
                                        {
                                            ArrayList altemp2 = d.Value as ArrayList;
                                            if (altemp2 != null && altemp2.Contains(realPhoneNumber))
                                            {
                                                Socket s = _acceptServersocketList[d.Key] as Socket;
                                                if (s != null)
                                                {
                                                    try
                                                    {
                                                        s.Send(receData);
                                                        ushort realMessageId = OperateAgreement.GetMessageIdInTransferMessageHead(realData);
                                                        LogService.WriteDebugLog2("flag==" + flag + "    转发成功----sendtoPhoneNumber：" + realPhoneNumber + "    realMessageId消息Id：0x"
                                                            + realMessageId.ToString("X2").PadLeft(4, '0') + "    phoneNumber:" + phoneNumber
                                                            + "    messageId:" + messageId.ToString("X2").PadLeft(4, '0'), DateTime.Now, "Retweet");
                                                    }
                                                    catch (Exception ex)
                                                    {
                                                        LogService.WriteDebugLog2("转发失败", DateTime.Now, "Retweet");
                                                        CommonRoutine.HandlingExceptions(ex);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                else if (messageId == ConstParameters.CmdTaxiTakeAPhotoReply
                                    || messageId == ConstParameters.CmdTaxiTakeAVideoReply
                                    || messageId == ConstParameters.CmdSendSmsToTaxiReply
                                      || messageId == ConstParameters.CmdSendSmsToTaxiReplyRightNow
                                    || messageId == ConstParameters.CmdSendNewsToTaxiReply
                                     || messageId == ConstParameters.CmdTaxiCutOilReply
                                    || messageId == ConstParameters.CmdTaxiMonitorReply
                                    || messageId == ConstParameters.CmdSendByClientPublicId
                                  )
                                {
                                    const int bb = ConstParameters.MBodySatrtIndex;
                                    string strIp = string.Format("{0}.{1}.{2}.{3}", realData[bb], realData[bb + 1], realData[bb + 2], realData[bb + 3]);
                                    Socket s = _acceptServersocketList[strIp + "c"] as Socket;
                                    if (s != null)
                                    {
                                        try
                                        {
                                            if (s.Connected)
                                            {
                                                s.Send(receData);
                                            }
                                            else
                                            {
                                                Console.WriteLine("连接断开");
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            CommonRoutine.HandlingExceptions(ex);
                                        }

                                    }
                                }
                                else if (messageId == ConstParameters.CmdLogoutInTransfer)
                                {
                                    ArrayList altemp1 = _acceptServertIpList[flag] as ArrayList;
                                    if (altemp1 != null) altemp1.Remove(phoneNumber);
                                }
                                else
                                {
                                    #region Register
                                    if (!_acceptServersocketList.Contains(flag))
                                    {
                                        _acceptServersocketList[flag] = tcpClient;
                                    }
                                    ArrayList altemp = _acceptServertIpList[flag] as ArrayList;
                                    if (altemp == null)
                                    {
                                        altemp = new ArrayList { phoneNumber };
                                    }
                                    else if (!altemp.Contains(phoneNumber))
                                    {
                                        altemp.Add(phoneNumber);
                                    }

                                    _acceptServertIpList[flag] = altemp;
                                    #endregion
                                }

                            }
                            #endregion
                        }
                    }
                }
                if (endindex > 0)
                {
                    receBufferBb.RemoveRange(0, endindex);
                }



            }
            #endregion
            _acceptServertIpList.Remove(flag);
            _acceptServersocketList.Remove(flag);


        }


        private void InitControlAfterStopService()
        {
            spState.Text = @" 监听服务未启动 ...";
            button_Start.Enabled = true;
            button_Stop.Enabled = false;
        }



        private void InitControlAfterStartService()
        {
            spState.Text = @" 监听服务已启动 ...";
            button_Start.Enabled = false;
            button_Stop.Enabled = true;

        }

        private void button2_Click(object sender, EventArgs e)
        {
            string showtext = string.Empty;
            //_acceptServertIpList.Count.ToString();


            lock (_acceptServertIpList.SyncRoot)
            {
                foreach (DictionaryEntry dictionaryEntry in _acceptServertIpList)
                {
                    ArrayList al = ((ArrayList)dictionaryEntry.Value);
                    showtext = showtext + "接入服务器IP：" + dictionaryEntry.Key + "  Count:" + al.Count.ToString() + Environment.NewLine;
                    //foreach (string phoneNum in al)
                    //{
                    //    showtext = showtext + phoneNum + ",";
                    //}
                    //showtext += Environment.NewLine;
                }
            }
            MessageBox.Show(showtext);
        }

        private void TransferMainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            
            Environment.Exit(0);
        }

        private void TransferMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("是否确定关闭中转服务器？", "警告：", MessageBoxButtons.OKCancel)
             == DialogResult.Cancel)
            {
                e.Cancel = true;
                return;
            }
        }
    }
}
